/**
 * 修改类型声明
 *
 * let a,b
 *
 * 修改为
 * let a
 * let b
 */

import generate from '@babel/generator'
import { parse } from '@babel/parser'
import traverse from '@babel/traverse'
import * as types from '@babel/types'

import fs from 'node:fs'
import path from 'node:path'

const target = path.resolve(__dirname, '../demo/05.js')

const content = fs.readFileSync(target, {
	encoding: 'utf-8',
})

let ast = parse(content, {
	sourceType: 'module',
})

traverse(ast, {
	/**
	 * 变量声明
	 * @param path
	 */
	VariableDeclaration(path) {
		let declarations = path.node.declarations
		// 只针对 path.node里面 声明有多个的情况处理，已经是单个的，不管
		if (declarations.length > 1) {
			const list = declarations.slice(1)

			const first = declarations.shift()
			// ts里面就需要这样做一下类型判断， 判断我们拿出来的节点是一个 类型声明节点
			if (types.isVariableDeclarator(first)) {
				// 把原来的多个声明改为一个
				path.node.declarations = [first]
			}

      // 注意： 这里要考虑2种情况，一是全局环境，也就是global 最外层的声明， 另一种是函数作用域里面的变量声明要改写
			if ((path.parent.type === 'Program' || path.parent.type === 'BlockStatement') && path.parent.body) {
        // 逐个遍历，把节点插入到父节点中
				list.forEach((item) => {
          // 先拿到之前的声明，之前是 let, 改为多行声明仍旧用let,之前为 const，仍旧用const
          let kind = path.node.kind
					const currentNode = types.variableDeclaration(kind, [
						types.variableDeclarator(
							// 原来的名字
							item.id,
							// 原来的值
							item.init
						),
					])

					currentNode.declarations = [item]

					// 在指定位置插入，不能直接  body.push
					// body.splice(pos + 1, 0, currentNode)
					path.insertAfter(currentNode)
				})
			}
		}
	},

  /**
   * 在这个案例中，会触发3次
   * 第一次 b = 10  属于表达式
   * 第二次 console.log() 属于表达式语句
    第三次 yuyu,ppp = "这种直接不写的"
   */
  ExpressionStatement(path) {
    console.log(1);
  }
})

console.log('----处理后的结果-----');

console.log(generate(ast).code)
